package org.javahispano.javacup.tacticas.tacticas_aceptadas.robertiano;

import java.awt.Color;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;

import org.javahispano.javacup.modelo.comando.Comando;
import org.javahispano.javacup.modelo.comando.ComandoGolpearBalon;
import org.javahispano.javacup.modelo.comando.ComandoIrA;
import org.javahispano.javacup.modelo.util.Constantes;
import org.javahispano.javacup.render.EstiloUniforme;
import org.javahispano.javacup.modelo.JugadorDetalle;
import org.javahispano.javacup.modelo.util.Posicion;
import org.javahispano.javacup.modelo.engine.SituacionPartido;
import org.javahispano.javacup.modelo.Tactica;
import org.javahispano.javacup.modelo.TacticaDetalle;

public class Loberos implements Tactica {
	
	private LinkedList<Comando> comandos = new LinkedList<Comando>();

	/**
	 * Por defecto
	 */
	Posicion alineacion1[]=new Posicion[]{
	        new Posicion(0.2595419847328244,-50.41044776119403),
	        new Posicion(-14.265734265734267,-33.73303167420815),
	        new Posicion(0.7132867132867133,-31.59502262443439),
	        new Posicion(14.74125874125874,-33.970588235294116),
	        new Posicion(-14.74125874125874,-13.065610859728507),
	        new Posicion(12.363636363636363,-11.64027149321267),
	        new Posicion(-25.202797202797203,18.29185520361991),
	        new Posicion(25.44055944055944,21.855203619909503),
	        new Posicion(-0.7132867132867133,7.601809954751132),
	        new Posicion(-13.314685314685315,33.970588235294116),
	        new Posicion(13.314685314685315,33.02036199095023)
	    };

	Posicion alineacion2[]=new Posicion[]{
			new Posicion(0.2595419847328244,-50.41044776119403),
			new Posicion(-11.16030534351145,-31.082089552238806),
			new Posicion(11.16030534351145,-31.6044776119403),
			new Posicion(27.251908396946565,-27.94776119402985),
			new Posicion(-29.84732824427481,-26.902985074626866),
			new Posicion(-1.188811188811189,-17.57918552036199),
			new Posicion(-9.034965034965035,-4.751131221719457),
			new Posicion(3.090909090909091,-1.6628959276018098),
			new Posicion(0.23776223776223776,0.0),
			new Posicion(-19.020979020979023,-0.47511312217194573),
			new Posicion(19.020979020979023,-0.23755656108597287)
	};
	
	Posicion alineacion3[]=new Posicion[]{
			new Posicion(0.2595419847328244,-50.41044776119403),
			new Posicion(-8.55944055944056,-34.68325791855204),
			new Posicion(6.895104895104895,-35.15837104072398),
			new Posicion(24.013986013986013,-32.30769230769231),
			new Posicion(-20.20979020979021,-29.457013574660635),
			new Posicion(-4.27972027972028,-21.61764705882353),
			new Posicion(-19.25874125874126,-8.789592760180994),
			new Posicion(22.349650349650346,-11.402714932126697),
			new Posicion(3.090909090909091,-19.004524886877828),
			new Posicion(-4.9930069930069925,-7.839366515837104),
			new Posicion(8.797202797202797,-2.8506787330316743)
	};

    class TacticaDetalleImpl implements TacticaDetalle {

        public String getNombre() {
            return "Loberos";
        }

        public String getPais() {
            return "Sahara";
        }

        public String getEntrenador() {
            return "Maximo";
        }

        public Color getColorCamiseta() {
            return new Color(0, 102, 0);
        }

        public Color getColorPantalon() {
            return new Color(0, 0, 102);
        }

        public Color getColorFranja() {
            return new Color(102, 0, 102);
        }

        public Color getColorCalcetas() {
            return new Color(0, 0, 0);
        }

        public Color getColorPortero() {
            return new Color(0, 51, 51        );
        }

        public EstiloUniforme getEstilo() {
            return EstiloUniforme.FRANJA_VERTICAL;
        }

        public Color getColorCamiseta2() {
            return new Color(224, 93, 101);
        }

        public Color getColorPantalon2() {
            return new Color(219, 128, 56);
        }

        public Color getColorFranja2() {
            return new Color(170, 224, 87);
        }

        public Color getColorCalcetas2() {
            return new Color(45, 87, 251);
        }

        public Color getColorPortero2() {
            return new Color(131, 16, 91        );
        }

        public EstiloUniforme getEstilo2() {
            return EstiloUniforme.SIN_ESTILO;
        }

        class JugadorImpl implements JugadorDetalle {

            String nombre;
            int numero;
            Color piel, pelo;
            double velocidad, remate, presicion;
            boolean portero;
            Posicion posicion;

            public JugadorImpl(String nombre, int numero, Color piel, Color pelo,
                    double velocidad, double remate, double presicion, boolean portero) {
                this.nombre=nombre;
                this.numero=numero;
                this.piel=piel;
                this.pelo=pelo;
                this.velocidad=velocidad;
                this.remate=remate;
                this.presicion=presicion;
                this.portero=portero;
            }

            public String getNombre() {
                return nombre;
            }

            public Color getColorPiel() {
                return piel;
            }

            public Color getColorPelo() {
                return pelo;
            }

            public int getNumero() {
                return numero;
            }

            public boolean esPortero() {
                return portero;
            }

            public double getVelocidad() {
                return velocidad;
            }

            public double getRemate() {
                return remate;
            }

            public double getPresicion() {
                return presicion;
            }

        }

        public JugadorDetalle[] getJugadores() {
        	return new JugadorDetalle[]{
        			new JugadorImpl("Portero", 1, new Color(255,200,150), new Color(50,0,0),1.0d,0.7d,0.83d, true),
                    new JugadorImpl("Jugador", 2, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,0.5d, false),
                    new JugadorImpl("Jugador", 3, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,1.0d, false),
                    new JugadorImpl("Jugador", 4, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,1.0d, false),
                    new JugadorImpl("Jugador", 5, new Color(255,200,150), new Color(50,0,0),1.0d,0.5d,0.71d, false),
                    new JugadorImpl("Jugador", 6, new Color(255,200,150), new Color(50,0,0),1.0d,0.5d,0.62d, false),
                    new JugadorImpl("Jugador", 7, new Color(255,200,150), new Color(50,0,0),1.0d,0.27d,0.84d, false),
                    new JugadorImpl("Jugador", 8, new Color(255,200,150), new Color(50,0,0),1.0d,0.27d,0.85d, false),
                    new JugadorImpl("Centro", 9, new Color(255,200,150), new Color(50,0,0),1.0d,0.3d,0.76d, false),
                    new JugadorImpl("DelanteroIzquierda", 10, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,0.84d, false),
                    new JugadorImpl("DelanteroDerecha", 11, new Color(255,200,150), new Color(50,0,0),1.0d,1.0d,0.84d, false)
        	};
        }
    }

    TacticaDetalle detalle=new TacticaDetalleImpl();
    public TacticaDetalle getDetalle() {
        return detalle;
    }

    public Posicion[] getPosicionSaca(SituacionPartido sp) {
    return alineacion2;
    }

    public Posicion[] getPosicionRecive(SituacionPartido sp) {
    return alineacion3;
    }
    
    /**
     * En un pase, ángulo máximo que debe formar el triángulo comapañero-jugador-rival.
     * Asegurándote que el rival no va a estar muy cerca de la trayectoria de la bola
     */
    private final static double ANGULO_MAX_PASO = 5.0D;
    private final static double DISTANCIA_TIRO_ALTO = 30.0D;
    
//    TODO RGB mejorar el saque de centro (sale el jugador corriendo con el balón, no pasa)
    @Override
	public List<Comando> ejecutar(SituacionPartido sp) {
		//Limpia la lista de comandos
		comandos.clear();
		//Obtiene las posiciones de tus jugadores
		Posicion[] jugadores = sp.misJugadores();
		
//		Establecemos la posición por defecto de los jugadores
		setPosicionDefecto(jugadores, sp);
		
//		Manda a los jugadores que pueden recuperar el balón que lo recuperen y al resto a la posición de covertura.
		setPosicionesRecuperacionCovertura(sp);
		
		//Instancia un generador aleatorio
		Random r = new Random();
		//Recorre la lista de mis jugadores que pueden rematar
		for (int jugador : sp.puedenRematar()) {
//			Si el jugador tiene indice 10 u 11
			if (jugador == 9 || jugador == 10 ) {
				setComandosDelanteros(jugadores, jugador, sp, r);
				
			}else if ( jugador == 8 ){
				int jugadorDestino = getJugadorDestino(r, jugador, jugadores, sp, new int[]{9, 10});
				if (jugadorDestino != jugador){
					addPase(jugadores, jugador, jugadorDestino);
				}else{
//					TODO RGB si no tengo a quien pasar, que hago?? paso al hueco!!--> tengo que hacerlo
					comandos.add(new ComandoIrA(jugador, direccionCorrer(jugadores[jugador], sp.rivales())));
					comandos.add(new ComandoGolpearBalon(jugador));
				}
			}else if ( jugador == 7 ){
//				intenta pasar primero al delantero de su banda
				int jugadorDestino = getJugadorDestino(r, jugador, jugadores, sp, new int[]{10, 9, 8});
				if (jugadorDestino != jugador){
					addPase(jugadores, jugador, jugadorDestino);
				}else{
//					TODO RGB si no tengo a quien pasar, que hago?? paso al hueco!!--> tengo que hacerlo
					comandos.add(new ComandoIrA(jugador, direccionCorrer(jugadores[jugador], sp.rivales())));
					comandos.add(new ComandoGolpearBalon(jugador));
				}
			}else if ( jugador == 6 ){
//				intenta pasar primero al delantero de su banda
				int jugadorDestino = getJugadorDestino(r, jugador, jugadores, sp, new int[]{9, 10, 8});
				if (jugadorDestino != jugador){
					addPase(jugadores, jugador, jugadorDestino);
				}else{
//					TODO RGB si no tengo a quien pasar, que hago?? paso al hueco!!--> tengo que hacerlo
					comandos.add(new ComandoIrA(jugador, direccionCorrer(jugadores[jugador], sp.rivales())));
					comandos.add(new ComandoGolpearBalon(jugador));
				}
			}else if ( jugador == 5 ){
//				intenta pasar primero al delantero de su banda
				int jugadorDestino = getJugadorDestino(r, jugador, jugadores, sp, new int[]{8, 7, 10, 9, 6, 4});
				if (jugadorDestino != jugador){
					addPase(jugadores, jugador, jugadorDestino);
				}else{
//					TODO RGB si no tengo a quien pasar, que hago?? paso al hueco!!--> tengo que hacerlo
					comandos.add(new ComandoIrA(jugador, direccionCorrer(jugadores[jugador], sp.rivales())));
					comandos.add(new ComandoGolpearBalon(jugador));
				}
			}else if ( jugador == 4 ){
//				intenta pasar primero al delantero de su banda
				int jugadorDestino = getJugadorDestino(r, jugador, jugadores, sp, new int[]{8, 6, 9, 10, 5});
				if (jugadorDestino != jugador){
					addPase(jugadores, jugador, jugadorDestino);
				}else{
//					TODO RGB si no tengo a quien pasar, que hago?? paso al hueco!!--> tengo que hacerlo
					comandos.add(new ComandoIrA(jugador, direccionCorrer(jugadores[jugador], sp.rivales())));
					comandos.add(new ComandoGolpearBalon(jugador));
				}
			}else if ( jugador == 3 ){
//				intenta pasar primero al delantero de su banda
				int jugadorDestino = getJugadorDestino(r, jugador, jugadores, sp, new int[]{6, 8, 7, 5, 4});
				if (jugadorDestino != jugador){
					addPase(jugadores, jugador, jugadorDestino);
				}else{
//					TODO RGB si no tengo a quien pasar, que hago?? paso al hueco!!--> tengo que hacerlo
					comandos.add(new ComandoIrA(jugador, direccionCorrer(jugadores[jugador], sp.rivales())));
					comandos.add(new ComandoGolpearBalon(jugador));
				}
			}else if ( jugador == 2 ){
//				intenta pasar primero al delantero de su banda
				int jugadorDestino = getJugadorDestino(r, jugador, jugadores, sp, new int[]{6, 8, 4, 5});
				if (jugadorDestino != jugador){
					addPase(jugadores, jugador, jugadorDestino);
				}else{
//					TODO RGB si no tengo a quien pasar, que hago?? paso al hueco!!--> tengo que hacerlo
					comandos.add(new ComandoIrA(jugador, direccionCorrer(jugadores[jugador], sp.rivales())));
					comandos.add(new ComandoGolpearBalon(jugador));
				}
			}else if ( jugador == 1 ){
//				intenta pasar primero al delantero de su banda
				int jugadorDestino = getJugadorDestino(r, jugador, jugadores, sp, new int[]{7, 8, 5, 4});
				if (jugadorDestino != jugador){
					addPase(jugadores, jugador, jugadorDestino);
				}else{
//					TODO RGB si no tengo a quien pasar, que hago?? paso al hueco!!--> tengo que hacerlo
					comandos.add(new ComandoIrA(jugador, direccionCorrer(jugadores[jugador], sp.rivales())));
					comandos.add(new ComandoGolpearBalon(jugador));
				}
//				Si es el portero
			} else if ( jugador == 0 ) {
//				pasamos a los jugadores que no sean defensa
				int jugadorDestino = getJugadorDestino(r, jugador, jugadores, sp, new int[]{4, 5, 6, 7, 8, 9, 10});
				comandos.add(new ComandoGolpearBalon(jugador, jugadores[jugadorDestino], 1, 20 + r.nextInt(20)));
			}
		}
		return comandos;
	}
    
	private void setPosicionDefecto(Posicion[] jugadores, SituacionPartido sp){
    	int[] rivalesCubiertos = new int[11];
    	int cont = 0;
    	
    	for (int i = 0; i < jugadores.length; i++) {

//			Rival más proximo a mi alineación que no este cubierto
			final int rivalProx = alineacion1[i].indiceMasCercano(sp.rivales(), rivalesCubiertos);
//			si el rival más cercano a mi alineación está a menos de 11
			if ( alineacion1[i].distancia( sp.rivales()[rivalProx] ) < 11 ){
				final Posicion posCobertura;
				final Posicion posRival = sp.rivales()[rivalProx];
				final double anguloRivalBalon = posRival.angulo( sp.balon() );
//				obtenemos la posición de 5ud en la dirección de la bola
				posCobertura = posRival.moverAngulo(anguloRivalBalon, 5);
				comandos.add(new ComandoIrA(i, posCobertura));
				rivalesCubiertos[cont++] = rivalProx;
			}else{// El rival más cercano está lejos para cubrirle
//			Ordena al jugador que se ubique segun la alineacion1
				comandos.add(new ComandoIrA(i, alineacion1[i]));
			}
		}
    }
	
	private void setPosicionesRecuperacionCovertura(SituacionPartido sp) {
		//Si no saca el rival
		if (!sp.sacaRival()) {
			//Obtiene los datos de recuperacion del balon
			int[] recuperadores = sp.getRecuperacionBalon();
			//Si existe posibilidad de recuperar el balon
			if (recuperadores.length > 1) {
				//Obtiene las coordenadas del balon en el instante donde
				//se puede recuperar el balon
				double[] posRecuperacion = sp.getTrayectoria(recuperadores[0]);
				Posicion recuperacion = new Posicion(posRecuperacion[0], posRecuperacion[1]);
				//Recorre la lista de jugadores que pueden recuperar
				for (int i = 1; i < recuperadores.length; i++) {
//					Si es saque de banda y el jugador es un delantero (10 u 11)
					if ( sp.saco() && (recuperadores[i] == 9 || recuperadores[i] == 10))
//						va a por el balón el lateral correspondiente (10 --> 7 y 11 --> 8)
						comandos.add(new ComandoIrA(recuperadores[i] == 9 ? 6 : 7,
								recuperacion));
					else if (recuperadores[i] == 0){
						int[] iteracionesParaRematarRivalAux = Arrays.copyOf(sp.iteracionesParaRematarRival(), sp.iteracionesParaRematarRival().length);
						Arrays.sort(iteracionesParaRematarRivalAux);
//						si mi portero va a tardar más iteraciones que el jugador rival en pillar la bola que no vaya a recuperarla
						if (sp.iteracionesParaRematar()[0] > iteracionesParaRematarRivalAux[0]){
//							TODO RGB no va a por la bola, se pone entre la posición de remate del rival y el centro de la portería
						}else{
							comandos.add(new ComandoIrA(recuperadores[i], recuperacion));
						}
					}else //Si es saque de banda y el jugador no es un delantero
						//Ordena a los jugadores recuperadores que se ubique
						//en la posicion de recuperacion
						comandos.add(new ComandoIrA(recuperadores[i], recuperacion));
				}
			}
		}
	}
    
    /**
     * jugador puede ser sólo 9 o 10 (10 u 11)
     * @param comandos
     * @param jugadores
     * @param jugador
     * @param sp
     * @param r
     */
    private void setComandosDelanteros(Posicion[] jugadores, int jugador, SituacionPartido sp, Random r){
    	final double distanciaArco = jugadores[jugador].distancia(Constantes.centroArcoSup);
    	
//    	TODO RGB Comprobar la distancia a la que los tiros a puerta efectivos
		if ( distanciaArco < 36.0D ){
			final Posicion dondeRematar = getADondeRematar(jugadores[jugador], sp.rivales(), sp.detalleJugadoresRivales());
			
			if (dondeRematar != null){
				final int angulo = 12 + r.nextInt(6);
				comandos.add(new ComandoGolpearBalon(jugador, dondeRematar, 1, angulo));
			}else{
				//condicion aleatoria
				if (r.nextBoolean()) {
					//Ordena que debe rematar al centro del arco
					final int angulo = 12 + r.nextInt(6);
					comandos.add(new ComandoGolpearBalon(jugador, Constantes.centroArcoSup, 1, angulo));
				} else if (r.nextBoolean()) {
					//Ordena que debe rematar al poste derecho
					final Posicion derecho = new Posicion(
							Constantes.posteDerArcoSup.getX() - Constantes.LARGO_ARCO / 6,
							Constantes.posteDerArcoSup.getY());
					final int angulo = 12 + r.nextInt(6);
					comandos.add(new ComandoGolpearBalon(jugador, derecho, 1, angulo));
				} else {
					//Ordena que debe rematar al poste izquierdo
					final Posicion izquierdo = new Posicion(
							 Constantes.posteIzqArcoSup.getX() + Constantes.LARGO_ARCO / 6,
							 Constantes.posteIzqArcoSup.getY());
					final int angulo = 12 + r.nextInt(6);
					comandos.add(new ComandoGolpearBalon(jugador, izquierdo, 1, angulo));
				}
			}
		}else{// estamos lejos de la portería
			int[] jugadoresDestino;
			if (jugador == 10)
				jugadoresDestino = new int[]{9, 7, 8};
			else
				jugadoresDestino = new int[]{10, 8, 8};
			
			final int jugadorDestino = getJugadorDestino(r, jugador, jugadores, sp, jugadoresDestino);
			//Si el receptor del balon es el que remata o el compañero está cubierto
			if ( jugador == jugadorDestino ) {
//				Corremos con el balon
				comandos.add(new ComandoIrA(jugador, direccionCorrer(jugadores[jugador], sp.rivales())));
				comandos.add(new ComandoGolpearBalon(jugador));
//				TODO RGB correr con el balón va a ser la última opción vamos a intentar pasar a una posición donde pueda llegar nuestro compañero
			}else{
//				Ordena que el jugador que puede rematar que de un pase
//				al jugador destino
				addPase(jugadores, jugador, jugadorDestino);
			}
		}
    }
    
    private void addPase(Posicion[] jugadores, int jugador, int jugadorDestino){
    	final double distancia = jugadores[jugador].distancia(jugadores[jugadorDestino]);
		final int angulo;
		if (distancia > DISTANCIA_TIRO_ALTO && distancia < (2 * DISTANCIA_TIRO_ALTO)){
			angulo = 20;
		}else if (distancia > (2 * DISTANCIA_TIRO_ALTO)){
			angulo = 35;
		}else{
			angulo = 2;
		}
	//Ordena que el jugador que puede rematar que de un pase al jugador destino
		comandos.add(new ComandoGolpearBalon(jugador, jugadores[jugadorDestino], 1, angulo));
    }
    
    /**
     * Calcula la mejor dirección para correr. Si el rivál más cercano, está muy cerca, corren en dirección 
     * perpendicular a él en el sentido que le acerque más a la portería.
     * @param pJugador
     * @param rivales
     * @return
     */
    private Posicion direccionCorrer(Posicion pJugador, Posicion[] rivales) {
    	final Posicion direccion;
    	boolean rivalEncontrado = false;
    	final int[] rivalProx = pJugador.indicesMasCercanos(rivales);
    	int cont = 0;
//    	Mientras no lo encontremos un rival que nos bloque y nos queden rivales por estudiar 
    	while ( !rivalEncontrado && cont < rivalProx.length){
//    		si el rival está por delante de nosotros
        	if (pJugador.getY() < rivales[rivalProx[cont]].getY()){
//        		si está lo suficientemente cerca como para intercertarme
        		if (pJugador.norma(rivales[rivalProx[cont]]) < 25){
        			rivalEncontrado = true;
        		}else{// si el jugador qu está más cerca está a más de 25 no hay peligro de que nos quiten la bola
        			break;
        		}
        	}else{
        		cont++;
        	}
    	}
//    	
    	if (rivalEncontrado){
    		final double anguloRival = pJugador.angulo(rivales[rivalProx[cont]]);
    		final double anguloDireccion;
    		if ( anguloRival > pJugador.angulo(Constantes.centroArcoSup))
    			anguloDireccion = anguloRival - (Math.PI / 2);
    		else
    			anguloDireccion = anguloRival + (Math.PI / 2);
    		direccion = pJugador.moverAngulo(anguloDireccion, 10);
    	}else{
//    		Corremos hacia la portería
    		direccion = Constantes.centroArcoSup;
    	}
    	
		return direccion;
	}

	/**
     * Comprueba donde está el portero. Calcula la mejor posición a la que rematar.
     * @param pRematador
     * @param rivales
     * @param detalleJugadoresRivales
     * @return
     */
    private Posicion getADondeRematar(Posicion pRematador, Posicion[] rivales,
			JugadorDetalle[] detalleJugadoresRivales) {
    	Posicion dondeRematar = null;
    	boolean porteroEncontrado = false;
    	int contador = 0;
		while ( !porteroEncontrado && contador < detalleJugadoresRivales.length) {
			if (detalleJugadoresRivales[contador].esPortero())
				porteroEncontrado = true;
			else
				contador++;
		}
//		Si hemos encontrado el portero del equipo contrario (contador indica el índice)
		if (porteroEncontrado){
			final Posicion portero = rivales[contador];
//			calculamos el ángulo portero-rematador-palo_derecho
			final double anguloPRD = pRematador.angulo(portero) - pRematador.angulo(Constantes.posteDerArcoSup);
//			calculamos el ángulo portero-rematador-palo_izquierdo
			final double anguloPRI = pRematador.angulo(portero) - pRematador.angulo(Constantes.posteIzqArcoSup);
//			Si hay más hueco por la derecha (angulo derecho mayor) tiramos con a 3/4 del portero hacia la derecha
			if (Math.abs(anguloPRD) > Math.abs(anguloPRI)){
				dondeRematar = pRematador.moverAngulo(
						pRematador.angulo(portero) - ((3/4) * anguloPRD), 10.0D);
			}else{
//				Si hay más hueco por la izquierda (ángulo izquierdo mayor) tiramos con a 3/4 del portero hacia la izquierda
				dondeRematar = pRematador.moverAngulo(
						pRematador.angulo(portero) - ((3/4) * anguloPRI), 10.0D);
			}
		}
		return dondeRematar;
	}

	/**
     * Compueba si no hay nadie que pueda robar la bola si pasa al compañero. Si hay algún jugador 
     * en el triángulo isósceles con vertice el jugador, altura, la distancia al compañero y ángulo
     * distinto 2 * ANGULO_MAX_PASO.
     * En el caso de que el compañero esté lejos sólo comprueba que no haya nadie pegado al tirador,
     * que podría robarle la bola.
     * @param jugador
     * @return
     */
    private boolean isCompaCubierto(Posicion jugador, Posicion compa, SituacionPartido sp) {
    	final boolean isCompaCubierto;
    	final double distanciaCompa = jugador.distancia(compa);
    	Posicion[] rivales = sp.rivales();
    	
    	Posicion[] cubridores = getCubridores(rivales, jugador, compa, distanciaCompa);
    	
    	if (distanciaCompa > DISTANCIA_TIRO_ALTO && cubridores.length > 0){
    		final int cubridorPox = jugador.indiceMasCercano(cubridores);
    		final double distanciaAlCubridor = jugador.norma(cubridores[cubridorPox]);
    		if (distanciaAlCubridor > 4 && distanciaAlCubridor < 12)
    			isCompaCubierto = true;
    		else
    			isCompaCubierto = false;
    	}else{
    		isCompaCubierto = cubridores.length > 0;
    	}
		return isCompaCubierto;
	}
    
    private Posicion[] getCubridores(Posicion[] rivales, Posicion jugador, Posicion compa, double distanciaCompa){
    	final double anguloCompa = jugador.angulo(compa);
    	
    	List<Posicion> cubridores = new ArrayList<Posicion>();
    	for (Posicion rival : rivales){
    		final double anguloRival = jugador.angulo(rival);
    		
    		final double anguloRelativo = anguloRival - anguloCompa;
    		final double distanciaRival = jugador.norma(rival);
    		
    		if ( -ANGULO_MAX_PASO < anguloRelativo && anguloRelativo < ANGULO_MAX_PASO && distanciaRival < distanciaCompa)
    			cubridores.add(rival);
    	}
    	return cubridores.toArray(new Posicion[cubridores.size()]);
    }

    /**
     * Solo busca los jugadores cuyo numero este entre jugadoresDestino.
     * @param r
     * @param tirador
     * @param jugadores
     * @param jugadoresDestino lista con los número de los jugadores destino ordenados por preferencia, no puede estar vacía.
     * @return
     */
    private int getJugadorDestino(Random r, int tirador, Posicion[] jugadores, SituacionPartido sp, int[] jugadoresDestino ){
    	int count = 0;
		int jugadorDestino = -1;
		double distancia;
		boolean encontrado =  false;
//		Mientras no se ha encontrado el jugador destino y el contador es menor al número de jugadores destino
		while ( !encontrado && count < jugadoresDestino.length) {
			
			jugadorDestino = jugadoresDestino[count++];
			distancia = jugadores[tirador].norma(jugadores[jugadorDestino]);
			if (distancia > DISTANCIA_TIRO_ALTO)
				encontrado = true;
//			Tiene que comprobar si está libre
			if ( !isCompaCubierto(jugadores[tirador], jugadores[jugadorDestino], sp))
//				hemos encontrado el jugador destino
				encontrado = true;
		}
//		Si no encontramos a quien pasar
		if (!encontrado)
//			nosotros somos el jugados destino
			jugadorDestino = tirador;
		return jugadorDestino;
    }
    
}